Repository navigation
Conversation
|
CI note: the only failing check, Behavior portable serial 1, fails in the unrelated timing-sensitive tests/fm-supervision-host.test.sh (host wake hand-off wait_until timeout); this PR does not touch that area. |
|
Speaking as Kun's firstmate: thank you @trillium, this is a clear, small change and the rovo catch from review is a good one. What I checked at head Contract-class: new-default (my own read). Main specifies the raw escape hatch as passing the captain's command through as written. The existing test says "nothing else may rewrite the captain's own command" and asserts that the raw command is unchanged. This PR changes that default for every raw launch, which is why the tests needed VISION:
CI: the only red is One ask, whenever you have time: the "live" rows in the description are the spawn tests with a fake pane. Could you do one real raw launch with an actual harness CLI (a generic one, plus kimi or rovo if you can) and post what the agent received? You could also re-raise through |
|
Thanks for the review. I don't have kimi or rovo installed, so I can't test the raw launch against either of those. |
|
Closing: opened without intent. Sorry for the noise. |
|
Reopened: the earlier close was a mistake on my side. This PR stands as originally written. |
[Medium impact] The PR appears safe to merge; no outstanding findings remain. Reviews (4) · Last reviewed commit: "no-mistakes(ci): ci-3 (Greptile: shell c..." · Reviewed by Greptile |
f6c486d to
122ec52
Compare
A raw launch command skipped the launch-brief arg that every named adapter template embeds, so the agent started at an empty prompt. Append it after the caller's own argv. Kimi rejects a positional prompt and keeps its post-readiness brief pointer, and a command that already names __BRIEF__ is left alone.
…d of a known harness
122ec52 to
f9cab7c
Compare
…he rule it breaks: the launch brief is only appended automatically when the raw command is a plain single command, so the appended argument actually reaches the agent's argv. A trailing `#` comment breaks that rule because the shell treats the appended brief as part of the comment. That means `codex --model x # use default permissions` would start the worker with no task and no warning. All the places this rule must hold: - the metacharacter check in `raw_launch_takes_brief` (`bin/fm-spawn.sh`), which is the one place every append decision goes through, both the claude doorbell path and the typed-envelope path; - the function's comment block; - the usage text in the fm-spawn header. Changes: - `bin/fm-spawn.sh`: added `*'#'*` to the metacharacter case in `raw_launch_takes_brief`. A raw command containing `#` now fails the check and goes down the existing path: it launches exactly as given, with the existing one-line warning suggesting `__BRIEF__`. Added `#` to the character lists in the function comment and the header usage text. - `tests/fm-spawn-dispatch-profile.test.sh`: added `"codex --model x # use default permissions"` to the cases in `test_other_raw_launches_launch_unchanged_with_a_warning`. That test runs the real spawn and checks three things: it exits 0, the warning is printed, and the emitted launch is the unchanged command with no launch-brief appended. Added "commented" to the test's comment. Following the recorded decisions, nothing was changed for ci-1 (the accepted label-gated Full suite) or ci-2 (a stale comment). Verification is not finished. The test-suite run, a confirmation run with the fix reverted, and the shellcheck run were still going in the background when I had to return this result, so I have no pass/fail output for them yet. By inspection, a command with `#` cannot reach the append branch now, and plain commands such as `codex --flag` and `claude --model x` still get the brief because they contain no `#`
Intent
main firstmate is down, please handle comments on kun chen firstmate PRs. For this PR (append the launch brief to raw launch commands): Greptile flagged a P1 at bin/fm-spawn.sh around line 2911. Compound raw launch commands must be handled explicitly or rejected with guidance to put BRIEF in the agent command. Failing shapes: 'custom-agent --flag; cleanup' (the brief becomes an argument to cleanup) and 'custom-agent --flag;' (the shell tries to run the encoded brief). Kun's firstmate also asked for one real raw launch with a real harness CLI, posting what the agent received, or re-raising with that evidence; the author already said kimi and rovo are not installed, so state that a generic harness only can be shown in the PR. The PR's intent step must complete in the pipeline attestation, and the lint step must report no open warning.
What Changed
bin/fm-spawn.shnow appends the launch brief to a raw launch command only when it is a plain single command for a known positional-prompt harness. The first word must be claude, codex, pi, pi-signed, omp, grok, cursor, gemini, devin, commandcode, cortex or muse. The command must contain none of$(, backtick,|,;,&,<,>or a newline, must not start with aVAR=valueassignment, and a wrapper such asenv,niceorsudodisqualifies it. Rawclaudegets the record-backed__BRIEFDOORBELL__. Other qualifying harnesses get"$(__OPINPUT__ encode launch-brief < __BRIEF__)"as their last argument.__BRIEF__/__BRIEFDOORBELL__are left as written, and rawkimi/rovostill get their brief pointer after the readiness gate. Any other raw command launches unchanged with a one-line warning to put__BRIEF__where the agent takes its prompt. That covers compound, substituted, wrapped and unknown-program commands, includingcustom-agent --flag; cleanupandcustom-agent --flag;. The spawn usage comment describes these rules.tests/fm-spawn-dispatch-profile.test.shadds tests for:codex --flaggetting the brief appended__BRIEF__placeholderNote: kimi and rovo are not installed on the author's machine, so the PR can only show a real raw launch through a generic harness.
Risk Assessment
✅ Low: The raw-launch brief append now follows the recorded conservative rule: it appends only for plain single commands of known positional-prompt harnesses, uses the doorbell for claude, and leaves kimi/rovo and commands with BRIEF alone; every other command launches unchanged with a warning. The round-1 fix (dropping opencode, polytoken and agy) is in place, and the behavior tests drive real spawn runs.
Testing
Ran the targeted spawn test file (all raw-launch tests pass). Then drove six real fm-spawn raw launches in a disposable lab on a private tmux socket. Two generic-harness compound shapes (Greptile's failing cases) launched unchanged with the warning, and neither the agent nor cleanup got a brief argument. Placing BRIEF in a compound command put the typed envelope at the placeholder. A real Claude Code worker launched raw got the doorbell, read the published brief record and began the brief. Wrapped and command-substituted launches of the real claude binary ran unchanged with the warning. Evidence is saved as CLI transcripts and pane captures; there is no UI surface. The lab was fully torn down, including one stray treehouse pool the first spawn created under ~/.treehouse before TREEHOUSE_ROOT was set on the lab tmux server. Overall result: all scenarios pass. kimi and rovo are not installed, so their exemption was covered only by the existing test.
Evidence: Live generic-harness raw launches (compound, trailing ';', __BRIEF__ placement)
Source: Live generic-harness raw launches (compound, trailing ';', BRIEF placement)
Evidence: Live real Claude Code raw launch: doorbell, published record, worker pane
Source: Live real Claude Code raw launch: doorbell, published record, worker pane
Evidence: Live adversarial raw launches of real claude (env-wrapped, $(...) argument)
Source: Live adversarial raw launches of real claude (env-wrapped, $(...) argument)
Evidence: Targeted spawn dispatch-profile test log
Source: Targeted spawn dispatch-profile test log
Evidence: What the generic agent received for 'custom-agent --flag; cleanup'
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed ✅
bin/fm-spawn.sh:2926- The known-harness allowlist inraw_launch_takes_briefincludes harnesses whose named templates do not take a positional prompt. The recorded decision says to append only for harnesses that 'take a positional prompt'. Three listed harnesses don't: opencode (template line 2678 uses--prompt, and OpenCode's positional argument is a project path), polytoken (line 2862 usesnew ... --prompt), and agy (line 2729 uses--prompt-interactive). Example: the raw commandopencode --model anthropic/xpasses every check, so the typed brief envelope is appended as a bare positional argument. OpenCode then reads the envelope as a project directory instead of a prompt, so the worker starts wrong or fails, with no warning. The same happens topolytoken --config-dir d newandagy --model m. Fix: remove opencode, polytoken and agy from the case list at bin/fm-spawn.sh:2926. Those raw commands then take the warning path and launch unchanged. Also update the header text at bin/fm-spawn.sh:246-247, which promises the brief to 'a known harness that takes a positional prompt'.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bash tests/fm-spawn-dispatch-profile.test.sh(the targeted spawn test file containing the new raw-launch tests; all passed, including raw rovo no-brief, plain known harness gets brief, raw claude doorbell, other raw launches unchanged with warning, compound BRIEF placement, and the unmodified chained/inherited-git-config originals)Live lab:bin/fm-spawn.sh rawlab-cmpd <lab>/projects/notes --mode local-only --yolo on 'custom-agent --flag; cleanup'with an argv-dumping custom-agent and cleanup on PATHLive lab:bin/fm-spawn.sh rawlab-trail ... 'custom-agent --flag;'Live lab:bin/fm-spawn.sh rawlab-place ... 'custom-agent --flag "$(__OPINPUT__ encode launch-brief < __BRIEF__)"; cleanup'Live lab with real Claude Code CLI:bin/fm-spawn.sh rawlab-claude ... 'claude --model haiku --setting-sources project,local', then captured the worker pane on the fm-lab socketLive lab adversarial with real claude binary:'env -u CLAUDECODE claude --version'and'claude --model $(echo haiku | tr -d x) --version'Teardown: killed the fm-lab tmux server, removed the lab's ~/.claude.json trust entries with an atomic replace (3 removed, 0 remaining), removed the stray ~/.treehouse/notes-24f9ca pool created by the first lab spawn, the /tmp/fm-rawlab-* task temp dirs, and the lab home✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.